/**
 * 
 */
package org.vsg.common.pagination;

import java.util.List;

import org.vsg.common.pagination.carrier.GroupingValueCarrier;
import org.vsg.common.pagination.carrier.RecordLimitCarrier;
import org.vsg.common.pagination.carrier.ValueCarrier;
import org.vsg.common.pagination.datatrans.DataTransformer;
import org.vsg.common.pagination.datatrans.PaginationProvider;
import org.vsg.common.pagination.keyword.PaginationKeyword;
import org.vsg.common.pagination.processor.PaginationProcessor;

/**
 * @author Bill Vison
 *
 */
public class GenericPaginationMaker implements PaginationMaker {

	private PaginationProvider provider;
	
	
	/* (non-Javadoc)
	 * @see org.vsg.commons.util.pagination.PaginationMaker#setProvider(org.vsg.commons.util.pagination.PaginationProvider)
	 */
	public void setProvider(PaginationProvider provider) {
		// TODO Auto-generated method stub
		this.provider = provider;
	}

	/* (non-Javadoc)
	 * @see org.vsg.commons.util.pagination.PaginationMaker#newPagination(org.vsg.commons.util.pagination.processor.PaginationProcessor)
	 */
	public Pagination newPagination(PaginationProcessor processor) throws PaginationException {
		// TODO Auto-generated method stub
		DataTransformer transformer = provider.getDataTransformer();
		
		// --- run the processor for total record ---
		int totalRecords = processor.getTotalRecords(transformer);
		
		// --- run the processor for get the list ---
		List dataList = processor.getPaginationList(transformer);
		

		processor.initProcessor();
		
		Object carrierObj = transformer.getImplicitValue(PaginationKeyword.TFS_CARRIER);
		
		
		Pagination page = null;
		// --- handle different carrier
		if (carrierObj instanceof ValueCarrier) {
			page = createPagination( transformer , (ValueCarrier)carrierObj , totalRecords , dataList );
		}
		else if (carrierObj instanceof RecordLimitCarrier) {
			page = createPagination( transformer , (RecordLimitCarrier)carrierObj , totalRecords , dataList );
		}
		
		
		// --- create different pagination implement ---

		return page;
	}
	
	private Pagination createPagination(DataTransformer transformer , ValueCarrier carrier , int totalRecords , List dataList) throws PaginationException{

		int pageIndex = ((Integer)transformer.getImplicitValue(PaginationKeyword.TFS_PAGE_INDEX)).intValue();
		int pageSize = ((Integer)transformer.getImplicitValue(PaginationKeyword.TFS_ROWS)).intValue();
		
		
		AbstractPagination page = null;
		
		if (carrier instanceof GroupingValueCarrier) {
			int groupSize = ((Integer)transformer.getImplicitValue(PaginationKeyword.TFS_GROUPING_SIZE)).intValue();

			page = new CommonAdvancePaginationImpl();
			AbstractAdvancedPagination apage = (AbstractAdvancedPagination)page;
			apage.setGroupingSize(groupSize);

		}
		
		// use commaon pagination
		else {
			page = new CommonPaginationImpl();
		}
		
		page.setDataList(dataList);
		page.setTotalRecord(totalRecords);
		page.setPageSize(pageSize);
		page.setPageIndex(pageIndex);
		
		page.initAfterPropSet();
		
		return page;
	}
	
	/**
	 * set the limit record limit
	 * @param transformer
	 * @param carrier
	 * @param totalRecords
	 * @param dataList
	 * @return
	 */
	private Pagination createPagination(DataTransformer transformer , RecordLimitCarrier carrier , int totalRecords , List dataList) throws PaginationException{
		
		int offset = (Integer)transformer.getImplicitValue(PaginationKeyword.TFS_DATA_OFFSET);
		int rows = (Integer)transformer.getImplicitValue(PaginationKeyword.TFS_ROWS);		
		
		int pageIndex = (int)Math.ceil( (double)offset / rows );
		
		AbstractPagination page = new CommonPaginationImpl();
		page.setDataList(dataList);
		page.setTotalRecord(totalRecords);
		page.setPageSize(rows);
		page.setPageIndex(pageIndex);
		
		return page;
	}
	
	
}
